package com.tools.web.interceptor.auth._common;

import com.tools.common.object.Note;
import com.tools.common.object.json.JsonKit;
import com.tools.common.thread.Timeunit;
import com.tools.middle.redis.client.JedisPlus;
import com.tools.web.interceptor.auth.*;

import java.util.Objects;

/**
 * JedisPlus 客户端操作 Redis 实现的 “用户单在线记录” 的 AuthenticationManager 身份认证拦截器
 * */
@Note("JedisPlus 客户端操作 Redis 实现的 “用户单在线记录” 的 AuthenticationManager 身份认证拦截器")
public abstract class JedisPlusSingleAuthenticationManager extends GenericAuthenticationManager implements SingleRedisLuaScript {

    @Note("操作 Redis 的 JedisPlus 客户端，依靠 Jedis 实现")
    private final JedisPlus jedisPlus;

    protected JedisPlusSingleAuthenticationManager(JedisPlus jedisPlus, AuthSource source, AuthUserService authUserService) {
        super(source, authUserService);
        this.jedisPlus = Objects.requireNonNull(jedisPlus, "操作 Redis 的 JedisPlus 客户端为 null");
    }

    @Override
    public final Timeunit getTimeunitUsedBySubclass() {
        return Timeunit.SECOND;
    }

    @Override
    protected GetAuthUserResult getAuthUser(String key, AuthToken decryptedAuthToken) {
        try {
            String json = (String) this.jedisPlus.get(key);
            if(json != null) {
                SingleAuthUser authUser = JsonKit.toEntity(json, SingleAuthUser.class);
                boolean b1 = Objects.equals(authUser.getUuid(), decryptedAuthToken.getUuid());
                boolean b2 = Objects.equals(authUser.getLoginDeviceType(), decryptedAuthToken.getLoginDeviceType());
                if(b1 && b2) {
                    return new GetAuthUserResult(true, authUser);
                }
                return new GetAuthUserResult(false, null);
            }
            return super.protected_getResultIfExpired(decryptedAuthToken);
        } finally {
            this.jedisPlus.close();
        }
    }

    @Override
    protected void setAuthUser(String key, AuthUser srcAuthUser, AuthToken decryptedAuthToken) {
        try {
            SingleAuthUser authUser = (SingleAuthUser) srcAuthUser;
            authUser.setUuid(decryptedAuthToken.getUuid());
            authUser.setLoginDeviceType(decryptedAuthToken.getLoginDeviceType());
            authUser.setLoginUserType(decryptedAuthToken.getLoginUserType());
            String json = JsonKit.toJSON(authUser);
            long expiration = this.getTimeunitUsedBySubclass().cast(decryptedAuthToken.getExpirationMill(), Timeunit.MILL);
            this.jedisPlus.setex(key, expiration, json);
        } finally {
            this.jedisPlus.close();
        }
    }

    @Override
    protected void removeAuthUser(String key) {
        try {
            this.jedisPlus.del(key);
        } finally {
            this.jedisPlus.close();
        }
    }

    @Override
    protected void updateAuthUser(String key, AuthUser authUser) {
        try {
            String json = (String) this.jedisPlus.get(key);
            if(json == null) return;
            SingleAuthUser oldAuthUser = JsonKit.toEntity(json, SingleAuthUser.class);
            authUser.copyAuthData(oldAuthUser);
            authUser.copyCustomData(oldAuthUser);
            Object user = authUser.getUser();
            oldAuthUser.setUser(user);
            String newJson = JsonKit.toJSON(authUser);
            this.jedisPlus.eval(UPDATE_AUTH_USER,
                    0, key, newJson);
        } finally {
            this.jedisPlus.close();
        }
    }

    @Override
    protected void protected_loginOut(String key, String loginDeviceType, String uuid) {
        this.removeAuthUser(key);
    }

}
